package com.sixkey.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sixkey.constant.CommonConstant;
import com.sixkey.constant.RedisConstant;
import com.sixkey.entity.*;
import com.sixkey.entity.vo.*;
import com.sixkey.exception.ServiceException;
import com.sixkey.mapper.DepartmentMapper;
import com.sixkey.mapper.UserMapper;
import com.sixkey.response.ResponseEnum;
import com.sixkey.service.IAuthorParticipantService;
import com.sixkey.service.IReservationService;
import com.sixkey.service.ISignService;
import com.sixkey.service.IUserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sixkey.utils.SecureUtils;
import io.lettuce.core.ScanArgs;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.ClusterOperations;
import org.springframework.data.redis.core.Cursor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author author
 * @since 2023-09-27
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Autowired
    private  RedisTemplate redisTemplate;

    @Autowired
    private  DepartmentMapper departmentMapper;

    @Autowired
    private  IAuthorParticipantService authorParticipantService;

    @Autowired
    private  ISignService signService;

    @Lazy
    @Autowired
    private IReservationService reservationService;

    /**
     * 获取用户分页数据
     * @param pageNo
     * @param pageSize
     * @param userVo
     */
    @Override
    public Page<User> queryList(Integer pageNo, Integer pageSize, UserVo userVo) {
        Page<User> pageInfo = new Page<>(pageNo, pageSize);
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        //添加过滤条件(模糊查询)
        wrapper.like(!StringUtils.isEmpty(userVo.getPhone()),User::getPhone,userVo.getPhone());
        wrapper.like(!StringUtils.isEmpty(userVo.getStatus()),User::getStatus,userVo.getStatus());
        wrapper.like(!StringUtils.isEmpty(userVo.getName()),User::getName,userVo.getName());
        //添加排序条件
        wrapper.orderByDesc(User::getUpdateTime);
        Page<User> userPage = this.page(pageInfo, wrapper);
        //设置部门名称
        userPage.getRecords().stream().forEach(item -> {
            item.setDeptName(departmentMapper.selectById(item.getDeptId()).getName());
        });
        return userPage;
    }

    /**
     * 修改用户状态
     * @param id
     * @param status
     */
    @Override
    public void updateStatus(Integer id, Integer status) {
        User user = baseMapper.selectById(id);
        user.setStatus(status);
        baseMapper.updateById(user);
    }

    /**
     * 批量或单个用户数据删除
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void removeBatch(List<Integer> id) {
        List<User> users = baseMapper.selectBatchIds(id);
        //过滤掉停用用户剩下就是启用中的用户
        List<User> list = users.stream().filter(user -> user.getStatus() == 0).collect(Collectors.toList());
        if(!CollectionUtils.isEmpty(list)){
            //说明有启用中的用户
            throw new ServiceException(ResponseEnum.USER_USED);
        }
        //批量或单个用户数据删除
        baseMapper.deleteBatchIds(id);
    }

    /**
     * 修改用户数据
     * @param user
     */
    @Override
    public void updateUser(User user) {
        //判断用户是否修改了密码
        User updateUser = baseMapper.selectById(user.getId());
        if(updateUser.getStatus() == CommonConstant.USER_STATUS_YES){
            //如果用户是处于启用状态，则需先禁用才能修改
            throw new ServiceException(ResponseEnum.USER_USED_JINYON);
        }
        Department department = departmentMapper.selectOne(new QueryWrapper<Department>().eq("name", user.getDeptName()));
        user.setDeptId(department.getId());
        baseMapper.updateById(user);
    }

    /**
     * 小程序端修改用户头像
     * @param updateUserVo
     */
    @Override
    public void apiUpdateUser(UpdateUserVo updateUserVo) {
        User user = this.getOne(new QueryWrapper<User>().eq("phone", updateUserVo.getPhone()));
        user.setAvatar(updateUserVo.getAvatar());
        this.updateById(user);
    }

    /**
     * 用户使用手机号注册及登录
     * @param
     * @return
     */
    @Override
    public Map<String, Object> apiPhoneDoLogin(String phone) {
        //1、根据用户名查询用户
        User user = this.getOne(new QueryWrapper<User>().eq("phone", phone));
        if(null == user){
           throw new ServiceException(ResponseEnum.FORBID_USER);
        }
        //2、查询用户是否被禁用
        if(user.getStatus() == CommonConstant.USER_STATUS_NO){
            throw new ServiceException(ResponseEnum.USER_JINYON);
        }
        //将登录用户注入到应用上下文
        StpUtil.login(user.getId());
        Map<String,Object> map = new HashMap<>();
        //4、返回用户信息及token
        map.put("user",user);
        map.put("token",StpUtil.getTokenValue());
        return map;
    }

    @Override
    public void saveUser(User user) {
        Department department = departmentMapper.selectOne(new QueryWrapper<Department>().eq("name", user.getDeptName()));
        user.setDeptId(department.getId());
        this.save(user);
    }

    @Override
    public User getUserById(Integer id) {
        User user = this.getById(id);
        Department department = departmentMapper.selectById(user.getDeptId());
        user.setDeptName(department.getName());
        return user;
    }

    /**
     * 获取签到用户信息
     * @param
     * @return
     */
    @Override
    public List<User> getSignUser(int id) {
        List<Sign> signList = signService.list(new QueryWrapper<Sign>().eq("reservation_id", id));
        if(CollectionUtils.isEmpty(signList)){
            return null;
        }
        List<String> phones = signList.stream().map(Sign::getPhone).collect(Collectors.toList());
        List<User> users = new ArrayList<>();
        phones.stream().forEach(item->{
            User user = this.getOne(new QueryWrapper<User>().eq("phone", item));
            users.add(user);
        });
        return users;
    }

    @Override
    public User getUserInfo(String phone) {
        User user = this.getOne(new QueryWrapper<User>().eq("phone", phone));
        return user;
    }

    @Override
    public Map<String,Object> doLogin(LoginVo loginVo) {
        User user = this.getOne(new QueryWrapper<User>().eq("name", loginVo.getName()));
        if(user == null) {
            throw new ServiceException(ResponseEnum.USERNAME_NOTFOUND);
        }
        if(!user.getPhone().equalsIgnoreCase(loginVo.getPhone())) {
            throw new ServiceException(ResponseEnum.PHONE_EXIST);
        }
        if(user.getRole().equalsIgnoreCase(CommonConstant.USER_ROLE_NORMAL)) {
            throw new ServiceException(ResponseEnum.USER_NORMAL);
        }
        //将登录用户注入到应用上下文
        StpUtil.login(user.getId());
        Map<String,Object> map = new HashMap<>();
        //4、返回用户信息及token
        map.put("user",user);
        map.put("token",StpUtil.getTokenValue());
        return map;
    }

}
